<template>
  <div class="legend">
    <!-- 图例控制 -->
    <div class="legend-front">
      <div class="legend-front-item" v-for="(item, index) in List" :key="index">
        <span class="content-title">{{ item.title }}</span>
        <div class="content-box">
          <div class="item" v-for="(i, idx) in item.content" :key="idx">
            <div class="item-color"></div>
            {{ i.label }}
            <el-checkbox
              class="legend-box"
              v-model="i.isShow"
              @change="switchLegendLayer(i)"
              size="large"
            />
          </div>
        </div>
      </div>
    </div>
  </div>
  <!-- 可以通过动态组件和 Map 结构结合的方式实现组件的复用和管理 -->
  <component
    :is="instance.component"
    ref="LegendPopUpRef"
    v-bind="instance.props"
    @close="removeComponent(id)"
    v-for="[id, instance] in componentMap"
    :key="id"
    :id="id"
  />
</template>

<script lang="ts" setup>
import {
  onMounted,
  ref,
  shallowRef,
  markRaw,
  getCurrentInstance,
  ComponentInternalInstance,
  nextTick,
} from "vue";
import * as Cesium from "cesium";
import LegendPopUp from "./popup/LegendPopUp.vue";

const { proxy } = getCurrentInstance() as ComponentInternalInstance;
// 定义存储组件的Map结构
const componentMap = new Map();
const componentRefs = new Map();
// 动态创建组件实例的方法
const createComponent = (id: string, props = {}) => {
  const instance = {
    component: LegendPopUp,
    props: {
      ...props,
      key: id, // 确保唯一key
    },
  };
  componentMap.set(id, instance);
  // 动态添加组件后需要强制刷新视图
  proxy!.$forceUpdate();
  return instance;
};

// 动态移除组件的方法
const removeComponent = (id) => {
  console.log("id", id);
  componentMap.delete(id);
  const element = getComponentInstance(id);
  if (element) {
    element.remove();
  }
  console.log('listeners', listeners.value)
  const listener = listeners.value.find((item) => item.id === id);
  console.log("listener", listener)
  if (listener) {
    window.viewer.scene.postRender.removeEventListener(listener);
    listeners.value = listeners.value.splice(listeners.value.findIndex((item) => item.id === id), 1)
  }
};

// 设置组件实例的模板引用
// const setComponentRef = (id, el) => {
//   // nextTick(() => {
//     console.log("id, el", id, el);
//     if (el && !el.__v_skip) {
//       componentRefs.set(id, el);
//     }
//   // });
// };

// 访问指定组件实例
const getComponentInstance = (id) => {
  return document.getElementById(id);
};
// 聚合监听事件，用于聚合图标移动
let removeListener;
// 地球拖动监听事件，用于弹窗移动
let listeners = ref<{ id: string; listener: any }[]>([]);
// 图例弹窗元素
const LegendPopUpRef = ref();
// 是否展示图例弹窗
const showPopUp = ref(false);
// 图例信息
const List = ref([
  {
    title: "图例",
    content: [
      {
        label: "图例1",
        layerName: "legendLayer1",
        isShow: false,
      },
    ],
  },
]);
// 添加地球点击事件
const addClickEvent = (layerName: string) => {
  let windowPosition;
  const canvas = window.viewer.scene.canvas;
  const mouseHandler = new Cesium.ScreenSpaceEventHandler(canvas);
  // 绑定鼠标移动事件
  mouseHandler.setInputAction((e) => {
    const catesian = window.viewer.scene.pick(e.endPosition);
    if (catesian) {
      document.body.style.cursor = "pointer";
    } else {
      document.body.style.cursor = "default";
    }
  }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
  // 绑定鼠标左点击事件
  mouseHandler.setInputAction((e) => {
    windowPosition = e.position; // 屏幕坐标
    const catesian = window.viewer.scene.pick(windowPosition);
    // 这个catesian中的id属性值可以获取所有聚合点位的信息
    console.log("catesian", catesian);
    showPopUp.value = !!catesian;
    if (catesian) {
      if (catesian.id && catesian.id.length > 0) {
        createComponent(catesian.id[0].id, {
          title: layerName,
        });
        console.log("componentMap2222", componentMap);
        nextTick(() => {
          // console.log("LegendPopUpRef", LegendPopUpRef);
          const LegendPopUpElement = getComponentInstance(catesian.id[0].id);
          console.log("LegendPopUp", LegendPopUp);
          console.log("LegendPopUpRef", LegendPopUpRef.value);
          console.log("LegendPopUpElement", LegendPopUpElement);
          if (showPopUp.value && LegendPopUpElement) {
            LegendPopUpElement.style.left = e.position.x + "px";
            LegendPopUpElement.style.top = e.position.y - 120 + "px";
            const listener = () => {
              let canvasPosition =
                window.viewer.scene.cartesianToCanvasCoordinates(
                  catesian.id[0].position._value
                );
              LegendPopUpElement.style.left = canvasPosition.x + "px";
              LegendPopUpElement.style.top = canvasPosition.y - 120 + "px";
            };
            listeners.value.push({
              id: catesian.id[0].id,
              listener,
            });
            window.viewer.scene.postRender.addEventListener(listener);
          }
        });
      }
    }
  }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
};
// 设置聚合样式
function customStyle(dataSource) {
  const pinBuilder = new Cesium.PinBuilder();
  const pin100 = pinBuilder.fromText("100+", Cesium.Color.RED, 48).toDataURL();
  const pin80 = pinBuilder.fromText("80+", Cesium.Color.ORANGE, 48).toDataURL();
  const pin60 = pinBuilder.fromText("60+", Cesium.Color.YELLOW, 48).toDataURL();
  const pin40 = pinBuilder.fromText("40+", Cesium.Color.GREEN, 48).toDataURL();
  const pin20 = pinBuilder.fromText("20+", Cesium.Color.BLUE, 48).toDataURL();
  const singleDigitPins = new Array(8);
  for (let i = 0; i < singleDigitPins.length; ++i) {
    singleDigitPins[i] = pinBuilder
      .fromText(`${i + 2}`, Cesium.Color.VIOLET, 48)
      .toDataURL();
  }
  if (Cesium.defined(removeListener)) {
    removeListener();
    removeListener = undefined;
  } else {
    removeListener = dataSource.clustering.clusterEvent.addEventListener(
      function (clusteredEntities, cluster) {
        cluster.label.show = false;
        cluster.billboard.show = true;
        cluster.billboard.id = cluster.label.id;
        cluster.billboard.verticalOrigin = Cesium.VerticalOrigin.BOTTOM;

        if (clusteredEntities.length >= 100) {
          cluster.billboard.image = pin100;
        } else if (clusteredEntities.length >= 80) {
          cluster.billboard.image = pin80;
        } else if (clusteredEntities.length >= 60) {
          cluster.billboard.image = pin60;
        } else if (clusteredEntities.length >= 40) {
          cluster.billboard.image = pin40;
        } else if (clusteredEntities.length >= 20) {
          cluster.billboard.image = pin20;
        } else {
          cluster.billboard.image =
            singleDigitPins[clusteredEntities.length - 2];
        }
      }
    );
  }

  // force a re-cluster with the new styling
  const pixelRange = dataSource.clustering.pixelRange;
  dataSource.clustering.pixelRange = 0;
  dataSource.clustering.pixelRange = pixelRange;
}
// 切换图例图层
function switchLegendLayer(item: any) {
  // 获取地图上的这个name的dataSource
  const targetDataSource = window.viewer.dataSources.getByName(item.layerName);
  if (targetDataSource && targetDataSource.length > 0) {
    targetDataSource.forEach((dataSource) => (dataSource.show = item.isShow));
  } else {
    fetch("china_points.json")
      .then((res) => res.json())
      .then((data) => {
        const dataSource = new Cesium.CustomDataSource(item.layerName);
        const dataSourcePromise = window.viewer.dataSources.add(dataSource);
        data.forEach((element) => {
          dataSource.entities.add({
            id: element.name,
            position: Cesium.Cartesian3.fromDegrees(...element.coordinates),
            // point: {
            //   pixelSize: 2, // 点大小
            //   color: Cesium.Color.YELLOW, // 图元颜色
            //   outlineColor: Cesium.Color.RED, // 轮廓颜色
            // },
            billboard: {
              // 是否显示
              show: true,
              // 图像地址，URI或Canvas的属性
              image: "image1.png",
              // 设置颜色和透明度
              color: Cesium.Color.WHITE.withAlpha(0.8),
              // 高度（以像素为单位）
              height: 10,
              // 宽度（以像素为单位）
              width: 10,
              // 逆时针旋转
              rotation: 20,
              // 大小是否以米为单位
              sizeInMeters: false,
              // 相对于坐标的垂直位置
              verticalOrigin: Cesium.VerticalOrigin.CENTER,
              // 相对于坐标的水平位置
              horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
              // 该属性指定标签在屏幕空间中距此标签原点的像素偏移量
              // pixelOffset: new Cesium.Cartesian2(10, 0),
              // 应用于图像的统一比例。比例大于会1.0放大标签，而比例小于会1.0缩小标签。
              scale: 1.0,
            },
          });
        });
        dataSourcePromise.then((source) => {
          source.clustering.enabled = true;
          source.clustering.clusterBillboards = true;
          source.clustering.minimumClusterSize = 10;
          customStyle(source);
        });
        addClickEvent(item.layerName);
      });
  }
}
onMounted(() => {
  console.log("componentMap", componentMap);
  console.log("componentRefs", componentRefs);
});
</script>

<style lang="scss" scoped>
.legend {
  position: absolute;
  left: 50px;
  bottom: 30px;
  box-sizing: border-box;
  z-index: 1000;
  display: flex;

  .legend-front {
    background: rgba(3, 36, 83, 0.8);
    border-radius: 14px;
    margin-right: 33px;
    padding-bottom: 0.1rem;

    .legend-front-item {
      position: relative;
      margin-right: 8px;
    }
  }

  .content {
    width: 200px;
    padding-left: 10px;
    background: rgba(3, 36, 83, 0.8);
    border-radius: 14px;
  }

  .content-title {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 167px;
    height: 34px;
    font-size: 20px;
    font-weight: 500;
    line-height: 24px;
    margin: 9px auto 0;
    border-radius: 14px;
    color: #ffffff;
    background: linear-gradient(
      90deg,
      rgba(14, 20, 32, 0.02) 0%,
      rgba(184, 205, 247, 0.31) 51%,
      rgba(14, 20, 32, 0) 100%
    );
  }

  .content-box {
    display: flex;
    flex-direction: column;
    flex-wrap: wrap;
    padding: 8px 0 0 10px;
  }

  .event-box {
    display: flex;
    flex-direction: column;
    flex-wrap: wrap;

    .item-box {
      .item-title {
        display: flex;
        align-items: center;
        font-size: 14px;
        font-weight: normal;
        line-height: 24px;
        color: #08c4e1;
      }
    }

    .item-hot-box {
      display: flex;
    }
  }

  .item {
    position: relative;
    padding-left: 5px;
    display: grid;
    grid-template-columns: 30px 1fr 50px;
    align-items: center;
    font-size: 18px;
    font-weight: normal;
    color: #ffffff;
    max-height: 40px;

    .item-color {
      width: 20px;
      height: 20px;
      border-radius: 50%;
      background-color: red;
    }

    .legend-box {
      margin: 0 auto;
      height: 35px;
    }

    &:last-child {
      margin-bottom: 0;
    }
  }
}

.legend-popup {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 350px;
  height: 200px;
  background-color: #fff;
  z-index: 1000;
}
</style>
